package icu.zqyhdm.blog.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import icu.zqyhdm.blog.mapper.ArticleMapper;
import icu.zqyhdm.blog.mapper.UserMapper;
import icu.zqyhdm.blog.service.ArticleService;
import icu.zqyhdm.blog.vo.TypeVo;
import icu.zqyhdm.exception.MyException;
import icu.zqyhdm.result.ResultCodeEnum;
import icu.zqyhdm.blog.entity.Article;
import icu.zqyhdm.blog.entity.Type;
import icu.zqyhdm.blog.mapper.TypeMapper;
import icu.zqyhdm.blog.service.TypeService;
import icu.zqyhdm.helper.JwtHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author lifu
 * @Date 2021/6/22 21:18
 */
@Service
public class TypeServiceImpl extends ServiceImpl<TypeMapper, Type> implements TypeService {
    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ArticleService articleService;

    //查询所有文章类型，类型名去重，并根据类型对应的文章数量降序排
    @Override
    @Cacheable(value = "blog:typeList",keyGenerator = "keyGenerator")
    public List<TypeVo> getAllType() {
        List<Type> typeList = baseMapper.selectList(Wrappers.emptyWrapper());
        List<TypeVo> typeVoList = BeanUtil.copyToList(typeList, TypeVo.class);

        Map<String,TypeVo> map = new HashMap<>();
        for(TypeVo typeVo : typeVoList){
            setTypeVoInfo(typeVo);
            //类型名去重
            if(map.containsKey(typeVo.getTypeName())){
                Integer rawCount = map.get(typeVo.getTypeName()).getArticleNum();
                Integer newCount = typeVo.getArticleNum() + rawCount;
                map.get(typeVo.getTypeName()).setArticleNum(newCount);
            }else {
                map.put(typeVo.getTypeName(),typeVo);
            }
        }
        typeVoList = new ArrayList<>(map.values());
        Collections.sort(typeVoList, new Comparator<TypeVo>() {
            @Override
            public int compare(TypeVo o1, TypeVo o2) {
                //按照value值，从大到小排序
                return o2.getArticleNum() - o1.getArticleNum();
            }
        });
        return typeVoList;
    }

    //查询某个用户的所有文章类型，并根据类型对应的文章数量降序排
    @Override
    @Cacheable(value = "blog:typeList", keyGenerator = "keyGenerator")
    public List<TypeVo> getTypeByUserId(Integer userId) {
        QueryWrapper<Type> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("author_id",userId);
        List<Type> typeList = baseMapper.selectList(queryWrapper);

        if(!typeList.isEmpty()){
            List<TypeVo> typeVoList = BeanUtil.copyToList(typeList, TypeVo.class);
            for(TypeVo typeVo : typeVoList) {
                setTypeVoInfo(typeVo);
            }
            Collections.sort(typeVoList, new Comparator<TypeVo>() {
                @Override
                public int compare(TypeVo o1, TypeVo o2) {
                    //按照value值，从大到小排序
                    return o2.getArticleNum() - o1.getArticleNum();
                }
            });
            return typeVoList;
        }
        return new ArrayList<TypeVo>();
    }

    //添加文章类型
    @Override
    @CacheEvict(value = "blog:typeList",allEntries = true)
    public void saveType(String token, String typeName) {
        //判断文章类型是否已存在
        Integer userId = JwtHelper.getUserId(token);
        QueryWrapper<Type> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("type_name",typeName).eq("author_id",userId);
        int count = baseMapper.selectCount(queryWrapper);
        if(count > 0){
            throw new MyException(ResultCodeEnum.TYPE_EXIST_ERROR);
        }
        Type type = new Type();
        //设置类型的所属用户
        type.setAuthorId(userId);
        type.setTypeName(typeName);
        int i = baseMapper.insert(type);
        if(i < 1){
            throw new MyException(ResultCodeEnum.NET_ERROR);
        }
    }

    //修改
    @Override
    @CacheEvict(value = "blog:typeList",allEntries = true)
    public void updateType(String token, Type type) {
        Integer userId = JwtHelper.getUserId(token);
        Integer authorId = type.getAuthorId();
        //用户的权限判断，非作者本人不能修改
        if(!authorId.equals(userId)){
            throw new MyException(ResultCodeEnum.AUTHORITY_ERROR);
        }
        //判断文章类型是否已存在
        String typeName = type.getTypeName();
        QueryWrapper<Type> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("type_name",typeName).eq("author_id",userId);
        int count = baseMapper.selectCount(queryWrapper);
        if(count > 0){
            throw new MyException(ResultCodeEnum.TYPE_EXIST_ERROR);
        }
        int i = baseMapper.updateById(type);
        if(i < 1){
            throw new MyException(ResultCodeEnum.NET_ERROR);
        }
    }
    //删除
    @Override
    @CacheEvict(value = "blog:typeList",allEntries = true)
    @Transactional(rollbackFor=Exception.class)
    public void deleteType(String token, Integer typeId) {
        //用户的权限判断，非管理员和作者本人不能修改
        Integer userId = JwtHelper.getUserId(token);
        Integer authorId = baseMapper.selectById(typeId).getAuthorId();
        Integer role = userMapper.selectById(userId).getRole();
        if(!(authorId.equals(userId) || role.intValue() == 1)){
            throw new MyException(ResultCodeEnum.AUTHORITY_ERROR);
        }
        //事务
        try {
            // 先删除类型表
            baseMapper.deleteById(typeId);
            // 文章类型对应的文章id
            List<Integer> articleIdList = articleMapper.selectList(new QueryWrapper<Article>().eq("type_id", typeId))
                    .stream().map(Article::getId).collect(Collectors.toList());
            // 删除文章
            for(Integer articleId : articleIdList){
                articleService.deleteArticle(token,articleId);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new MyException(ResultCodeEnum.NET_ERROR);
        }
    }

    //查
    @Override
    public TypeVo getTypeById(Integer typeId) {
        Type type = baseMapper.selectById(typeId);
        TypeVo typeVo = BeanUtil.copyProperties(type, TypeVo.class);
        return setTypeVoInfo(typeVo);
    }

    //把文章数量信息封装进文章类型
    private TypeVo setTypeVoInfo(TypeVo typeVo){
        QueryWrapper<Article> articleQueryWrapper = new QueryWrapper<>();
        articleQueryWrapper.eq("type_id",typeVo.getId());
        int count = articleMapper.selectCount(articleQueryWrapper);
        //把文章数量信息封装进文章标签
        typeVo.setArticleNum(count);
        return typeVo;
    }
}
